package src.zhuzi.spring.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class PerformProxy implements InvocationHandler{
	private Object target;//真实对象
	
	public Object getTarget() {//构造方法，给我们要代理的真实对象赋初值
		return target;
	}

	public void setTarget(Object target) {
		this.target = target;
	}

	private PerformProxy() {}//
	
	public static Object getInstance(Object o) {//获取代理对象
		PerformProxy handler = new PerformProxy();
		handler.target = o;
		/**
         * 通过Proxy的newProxyInstance方法在jvm运行时动态生成的我们的代理对象，我们来看看其三个参数
         * 第一个参数 handler.getClass().getClassLoader() ，我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
         * 第二个参数realSubject.getClass().getInterfaces()，我们这里为代理对象提供的接口是真实对象所实行的接口，表示我要代理的是该真实对象，这样我就能调用这组接口中的方法了
         * 第三个参数handler， 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
         */
		return Proxy.newProxyInstance(o.getClass().getClassLoader(),o.getClass().getInterfaces(),handler);
	}
	
	@Override
	/**
	 * proxy: 指代我们所代理的真实对象
	 * method: 指代的是我们所要调用真实对象的某个方法的Method对象
	 * args: 指代的是调用真实对象某个方法时接受的参数
	 */
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		long result = 0;
		if(method.isAnnotationPresent(PerformCheck.class)) {
			long start = System.currentTimeMillis();
			result = (long) method.invoke(target,args);//当代理对象调用真实对象的方法时，其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用
			long end = System.currentTimeMillis();
			System.out.println(method.getName()+"耗时："+(end-start));
		}else {
			result = (long) method.invoke(target,args);
		}
		System.out.println(result);
		return result;
	}
}